/* 
 * Copyright [2018] [Alex/libo(liboms@hotmail.com)]
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.hyts.schedule.executor.executor;


import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue;

import org.quartz.Trigger;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.hyts.schedule.executor.base.AbstractJobManager;
import com.hyts.schedule.executor.base.AbstractSchedulerManager;
import com.hyts.schedule.executor.base.AbstractTriggerManager;
import com.hyts.schedule.executor.base.BaseSchedulerManager;
import com.hyts.schedule.executor.daemon.MonitorSchedule;
import com.hyts.schedule.executor.handler.Task;
import com.hyts.schedule.executor.manager.DefaultJobManager;
import com.hyts.schedule.executor.manager.DefaultTriggerManager;
import com.hyts.schedule.executor.model.JobBean;
import com.hyts.schedule.executor.model.TriggerBean;

/** 
 * @title QuartzManager.java  
 * @package com.hyts.schedule.quartz  
 * @description 任务调度执行器操作  
 * @see com.hyts.schedule.executor.executor.DefaultScheduleExecutor
 * @author libo/Alex
 * @email liboms@hotmail.com/liboware@163.com  
 * @date 2018年5月18日 
 * @version V1.0 
 */
public class DefaultScheduleExecutor {

	/**  
	 * <p>日志输出器</p> 
	 * @fieldName logger
	 * @fieldType Logger
	 */ 
	private Logger logger = LoggerFactory.getLogger(DefaultScheduleExecutor.class);
	
	/**  
	 * <p>{字段的描述}</p> 
	 * @fieldName latch
	 * @fieldType CountDownLatch
	 */ 
	private volatile CountDownLatch latch;

	/**  
	 * <p>{字段的描述}</p> 
	 * @fieldName synchronousQueue
	 * @fieldType SynchronousQueue<JobBean>
	 */ 
	private static ConcurrentHashMap<String,JobBean> synchronousQueue;
	
	/**  
	 * <p>{字段的描述}</p> 
	 * @fieldName jobAndTrigger
	 * @fieldType BlockingQueue<TriggerBean>
	 */ 
	private BlockingQueue<TriggerBean> jobAndTrigger ;
	
	//静态代码
	static{
		synchronousQueue = new ConcurrentHashMap();
	}
	
	//实例代码
	{
		
		jobAndTrigger = new LinkedBlockingQueue<TriggerBean>();
	}
	
	/**  
	 * <p>任务管理器</p> 
	 * @fieldName jobManager
	 * @fieldType AbstractJobManager<AbstractJob<JobBean>, Trigger>
	 */ 
	private AbstractJobManager<Task, Trigger> jobManager;
	
	/**  
	 * <p>触发器管理器</p> 
	 * @fieldName triggerManager
	 * @fieldType AbstractTriggerManager<Trigger>
	 */ 
	private AbstractTriggerManager<TriggerBean> triggerManager;
	
	/**  
	 * <p>调度功能管理器</p> 
	 * @fieldName scheduleManager
	 * @fieldType AbstractSchedulerManager
	 */ 
	private AbstractSchedulerManager scheduleManager;
	
	/**  
	 * <p>是否启动守护轮训线程</p> 
	 * @fieldName isMonitor
	 * @fieldType boolean
	 */ 
	private boolean isMonitor;
	

	/**  
	 * @constructor：ScheduleExecutor  
	 * @param jobManager
	 * @param triggerManager  
	 */ 
	
	public DefaultScheduleExecutor(
			AbstractJobManager<Task, Trigger> jobManager,
			AbstractTriggerManager<TriggerBean> triggerManager,int syncCount,boolean isMonitor) {
		super();
		this.jobManager = jobManager;
		this.triggerManager = triggerManager;
		this.scheduleManager = new BaseSchedulerManager();
		this.isMonitor = isMonitor;
		if(this.isMonitor){
			this.latch = new CountDownLatch(syncCount);
		}
	}

	/**  
	 * @constructor：ScheduleExecutor  
	 * @param jobManager  
	 */ 
	public DefaultScheduleExecutor(
			AbstractJobManager<Task, Trigger> jobManager,int syncCount,boolean isMonitor) {
		super();
		this.jobManager = jobManager;
		this.triggerManager = new DefaultTriggerManager();
		this.scheduleManager = new BaseSchedulerManager();
		this.isMonitor = isMonitor;
		if(this.isMonitor){
			this.latch = new CountDownLatch(syncCount);
		}
	}

	/**  
	 * @constructor：ScheduleExecutor  
	 * @param triggerManager  
	 */ 
	public DefaultScheduleExecutor(AbstractTriggerManager<TriggerBean> triggerManager,int syncCount,boolean isMonitor) {
		super();
		this.triggerManager = triggerManager;
		this.jobManager = new DefaultJobManager();
		this.scheduleManager = new BaseSchedulerManager();
		this.isMonitor = isMonitor;
		if(this.isMonitor){
			this.latch = new CountDownLatch(syncCount);
		}
	}

	/**  
	 * @constructor：ScheduleExecutor    
	 */ 
	public DefaultScheduleExecutor(int syncCount,boolean isMonitor) {
		super();
		this.jobManager = new DefaultJobManager();
		this.triggerManager = new DefaultTriggerManager();
		this.scheduleManager = new BaseSchedulerManager();
		this.isMonitor = isMonitor;
		if(this.isMonitor){
			this.latch = new CountDownLatch(syncCount);
		}
	}
	

	/**  
	 * <b>execute</b>
	 * <p>执行操作方法</p>
	 * @param job
	 * @param trigger
	 * @exception
	 */ 
	public void submit(Task job,TriggerBean trigger){
		trigger.setTask(job);
		jobAndTrigger.add(trigger);
	}
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @exception
	 */ 
	public void stop(Object... para){
		if(!scheduleManager.isStoped()){
			scheduleManager.stop();
			logger.info("任务调度开始结束");
		}
	}
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param real
	 * @exception
	 */ 
	public void stop(boolean real){
		if(!scheduleManager.isStoped()){
			scheduleManager.stop(real);
			logger.info("任务调度开始结束");
		}
	}
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param serNo
	 * @exception
	 */ 
	public static void put(String serNo,JobBean jobBean){
		synchronousQueue.put(serNo, jobBean);
	}
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param serNo
	 * @return
	 * @exception
	 */ 
	public static boolean exsit(String serNo){
		return synchronousQueue.containsKey(serNo);
	}
	
	/**  
	 * <b>TODO(方法功能的描述)</b>
	 * <p>TODO(这里用一句话描述这个方法的作用)</p>
	 * @param serNo
	 * @return
	 * @exception
	 */ 
	public static JobBean get(String serNo){
		return synchronousQueue.get(serNo);
	}

	/**  
	 * @name latch's getter method
	 * @param none
	 * @return latch
	 */
	public CountDownLatch getLatch() {
		return latch;
	}
	
	/**
	 * @throws InterruptedException   
	 * <b>start</b>
	 * <p>启动执行方法操作</p>
	 * @param count
	 * @exception
	 */ 
	public void start() throws InterruptedException{
		if(!scheduleManager.isStarted()){
			scheduleManager.start();
			logger.info("任务调度开始启动");
		}
		jobAndTrigger.forEach(param->{
			jobManager.addJob(param.getTask(), triggerManager.addTrigger(param));
			if(isMonitor)
				latch.countDown();
		});
		if(isMonitor){
			this.getLatch().await();
			Thread domain = new Thread(new MonitorSchedule("监控线程执行",this));
			domain.setDaemon(true);
			domain.start();
		}
	}
   }
